"""
1. 什么是类和实例并说明他们之间的关系

在Python中，类（Class）是一种面向对象编程的基本概念。
类定义了对象的属性（也称为成员变量）和方法（也称为成员函数）。
对象是类的实例化（实例）。

类（Class）:
类是一个抽象的概念，用于描述具有相似属性和行为的对象的集合。
它是一种用户自定义的数据类型，通过关键字class来创建。
类定义了对象的通用属性和方法，并在创建对象时作为模板使用。

实例（Instance）:
实例是类的具体实现。当类定义之后，我们可以根据类创建多个对象，每个对象都被称为类的一个实例。这些实例具有类定义的属性和方法。

类和实例之间的关系:
类和实例之间是一种"类-实例"关系。
类是通用的模板，它定义了对象的属性和方法，而实例是根据类创建的具体对象。
比喻的话，我们可以将类比作为“汽车设计图”，描述了汽车的特征和功能。
而实例就是根据这个设计图制造出来的具体汽车，每辆汽车都有相同的特征和功能（即类的属性和方法），但它们的具体数据可能是不同的（比如汽车的颜色、牌照号等）。
通过实例化，我们可以创建多个对象，它们彼此之间相互独立，各自拥有类定义的属性和方法。
通过这种面向对象的编程方式，我们可以更好地组织和管理代码，实现代码的重用性，并更容易理解和维护复杂的系统。
"""

"""
2. 类的实例方法、类方法和静态分别如何定义举例说明，并总结它们的应用场景


实例方法（Instance Method）:
实例方法是最常见的类方法类型，它在类中定义，第一个参数通常是self，用于表示实例本身。实例方法可以访问和修改实例的属性，并且可以通过类的实例来调用。
应用场景:
实例方法适用于需要操作实例属性和在多个实例之间共享行为的情况。
例如，当需要根据实例的状态来执行某些操作时，实例方法是一个常见的选择。
"""


class MyClass1:
    def instance_method(self, arg1, arg2):
        # 访问实例属性
        self.attribute = arg1 + arg2
        return self.attribute


# 创建类的实例
obj = MyClass1()

# 调用实例方法
result = obj.instance_method(2, 3)
print(result)  # 输出: 5

"""
类方法（Class Method）:
类方法在类定义中使用@classmethod装饰器来标识，第一个参数通常是cls，用于表示类本身（类似于self表示实例）。
类方法可以访问类级别的属性，并且可以通过类本身来调用，也可以通过类的实例来调用。

应用场景:
类方法通常用于对类的属性进行操作或提供与类相关的功能。
例如，可以使用类方法来实现创建类的特殊实例或在创建实例之前进行一些初始化操作。
"""


class MyClass2:
    class_variable = 0

    @classmethod
    def class_method(cls):
        # 访问类属性
        cls.class_variable += 1
        return cls.class_variable


# 调用类方法
result1 = MyClass2.class_method()
result2 = MyClass2.class_method()

print(result1)  # 输出: 1
print(result2)  # 输出: 2

"""
静态方法（Static Method）:
静态方法在类定义中使用@staticmethod装饰器来标识，它不需要额外的参数来表示实例或类。
静态方法与类和实例无关，它类似于普通的函数，但是定义在类的名称空间中，因此可以通过类本身来调用。

应用场景:
静态方法适用于在类中定义与类和实例无关的独立功能。
当一个方法不需要访问类属性或实例属性时，可以将其定义为静态方法。静态方法在实现类的工具函数或辅助函数时非常有用。
"""


class MyClass3:
    @staticmethod
    def static_method(arg1, arg2):
        return arg1 + arg2


# 调用静态方法
result = MyClass3.static_method(2, 3)
print(result)  # 输出: 5

"""
总结:

实例方法：操作实例属性和方法，通过实例调用。
类方法：操作类属性和方法，通过类或实例调用，第一个参数是cls。
静态方法：与类和实例无关的独立函数，通过类或实例调用，没有额外的特殊参数。
"""

"""
3. MRO是什么，描述其查找顺序

在Python中，MRO（Method Resolution Order）是用于确定类继承关系中方法调用顺序的算法。
它用于确定在多重继承的情况下，当一个方法被调用时，解析器应该按照什么顺序查找该方法的实际定义。
Python使用C3线性化算法来计算MRO。C3线性化算法遵循以下三个原则：
1、子类优先原则：在多重继承中，子类的方法应该优先于父类的方法被调用。
2、单调性原则：在多重继承中，子类的方法调用顺序应该保持父类列表的顺序。
3、合并原则：如果有多个父类，且父类之间存在继承关系，那么在MRO中，子类的顺序应该在父类之前。

MRO查找顺序可以通过类的属性__mro__来查看，它是一个元组，按照解析顺序列出了类继承的线性化方法顺序。
"""


class A:
    def show(self):
        print("A")


class B(A):
    def show(self):
        print("B")


class C(A):
    def show(self):
        print("C")


class D(B, C):
    pass


obj = D()
obj.show()

"""
4. Mixin是什么，描述其应用场景
Mixin是一种设计模式，用于通过将一些功能单元打包成类，使其可以在多个类之间进行重用。
Mixin类通常不作为独立的类来使用，而是通过多重继承来混入到其他类中，以增强其功能。
Mixin类的特点是它们通常只包含一些方法，而不包含实例属性。
这样做的目的是让Mixin类的方法可以被其他类复用，而不会引入额外的状态或数据。

应用场景：
Mixin的设计模式在以下情况下特别有用：
1、功能复用：当多个类需要共享一些相同的功能时，可以将这些功能封装成Mixin类，并通过多重继承将其混入到这些类中。这样可以避免代码重复，提高代码复用性。
2、功能扩展：有时候，我们想要给一个已经存在的类增加一些额外的功能，但是不想修改原始类的代码。这时可以创建一个Mixin类，将额外的功能添加到这个Mixin类中，并通过多重继承将Mixin类混入到原始类中，从而实现功能扩展。
3、解耦代码：将一些独立的功能逻辑抽象成Mixin类，可以将这些功能与主要类的实现解耦，使得代码更加模块化和可维护。
"""

"""
5. 根据本周异常相关视频，总结try/except/else/finally的用法及如何自定义异常


`try/except/else/finally`是异常处理的一种语法结构，用于捕获和处理代码中可能出现的异常情况。

基本使用方式
1、try/except
try用于包含可能会引发异常的代码，如果在try中的代码发生异常，程序会立即跳转到与之匹配的except块，并执行其中的代码。
"""
try:
    # 可能引发异常的代码
    result = 10 / 0
except ZeroDivisionError:
    # 处理 ZeroDivisionError 异常
    print("Division by zero is not allowed.")
"""
2、try/except/else
else在try中的代码没有发生异常时执行。
如果在try中的代码没有引发异常，程序会跳过except，直接执行else中的代码。
"""
try:
    # 可能引发异常的代码
    result = 10 / 2
except ZeroDivisionError:
    # 处理 ZeroDivisionError 异常
    print("Division by zero is not allowed.")
else:
    # 没有异常发生时执行的代码
    print("Division successful. Result:", result)
"""
3、try/except/finally
finally中的代码无论是否发生异常都会执行。
通常用于释放资源或进行一些必要的清理操作，
比如关闭文件、关闭数据库连接等。
"""
try:
    # 可能引发异常的代码
    file = open("example.txt", "r")
    content = file.read()
except FileNotFoundError:
    # 处理 FileNotFoundError 异常
    print("File not found.")
finally:
    # 不管是否发生异常都会执行的代码
    file.close()
"""
4、try/except/else/finally
这是try/except/else/finally的完整形式，它结合了前面介绍的三种结构。
"""
try:
    # 可能引发异常的代码
    result = 10 / 2
except ZeroDivisionError:
    # 处理 ZeroDivisionError 异常
    print("Division by zero is not allowed.")
else:
    # 没有异常发生时执行的代码
    print("Division successful. Result:", result)
finally:
    # 不管是否发生异常都会执行的代码
    print("Cleanup resources.")
"""
自定义异常*
除了Python提供的内置异常类型，我们还可以自定义异常类型，以便更好地表示特定的错误情况。
自定义异常通常继承自Exception类或其子类。
"""


class MyCustomError(Exception):
    def __init__(self, message):
        self.message = message


try:
    age = int(input("Enter your age: "))
    if age < 0:
        raise MyCustomError("Age cannot be negative.")
except MyCustomError as e:
    print("Error:", e)
